<?php

namespace app\middleware;

use app\common\JwtHelper;
use think\Response;

class SecurityMiddleware
{
    protected $secretKey;
    protected $refreshedToken = null;

    public function __construct()
    {
        $this->secretKey = config('sign_secret_key');
    }

    public function handle($request, \Closure $next = null)
    {
        $path = $request->path();

        $authWhitelist = [
            'index/Api/sendSms',
            'index/Api/register',
            'index/Api/forgetPassword',
            'index/Api/login',
            'index/Api/getContactTel',
            'index/Api/bannerList',
            'index/Api/articleDetail',
            'index/Api/msgList',
            'index/Api/getVipArticle',
        ];

        $params = $request->param();
        if (!$this->verifySign($params)) {
            apiReturn(401, '签名验证失败或请求过期');
        }
        if (!in_array($path, $authWhitelist)) {
            $authHeader = $request->header('authorization', '');
            if (!$authHeader || stripos($authHeader, 'Bearer ') !== 0) {
                apiReturn(401, '缺少Authorization头或格式错误');
            }

            $token = substr($authHeader, 7);
            $user_id = $this->validateToken($token);
            if (!$user_id) {
                apiReturn(401, '无效的身份认证');
            }

            $request->user_id = $user_id;
        }

        // 手动执行控制器后逻辑（TP5不支持中间件next的结构）
        $response = null;
        if ($next instanceof \Closure) {
            $response = $next($request);
        }

        if (!$response) {
            $response = response();
        }

        if ($response instanceof Response) {
            $response->header([
                                  'X-Frame-Options' => 'DENY',
                                  'X-Content-Type-Options' => 'nosniff',
                                  'Content-Security-Policy' => "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';",
                              ]);

            if (!empty($this->refreshedToken)) {
                $response->header('X-Refreshed-Token', $this->refreshedToken);
            }
        }

        return $response;
    }

    protected function validateToken($token)
    {
        $payload = JwtHelper::verifyToken($token);
        if (!$payload || empty($payload['user_id'])) {
            return false;
        }

        if (JwtHelper::shouldRefreshToken($payload)) {
            $this->refreshedToken = JwtHelper::createToken(['user_id' => $payload['user_id']]);
        }

        return $payload['user_id'];
    }

    protected function verifySign($params)
    {
        if (empty($params['sign']) || empty($params['timestamp'])) {
            // 记录日志：缺少必要的签名参数
            return false;
        }

        $sign = $params['sign'];
        $timestamp = intval($params['timestamp']);

        // 时间戳验证逻辑保持不变
        if (abs(time() - $timestamp) > 3600) {
            // 记录日志：时间戳过期
            return false;
        }

        $paramsCopy = $params;
        unset($paramsCopy['sign']);

        // 记录用于计算签名的原始参数
        ksort($paramsCopy);
        $str = http_build_query($paramsCopy);
        $calcSign = hash_hmac('sha256', $str, $this->secretKey);

        // 如果签名不匹配，记录详细信息用于调试
        if (!hash_equals($calcSign, $sign)) {
            // 记录日志：签名不匹配，计算出的签名是$calcSign，收到的签名是$sign
            return false;
        }

        return true;
    }

}
